package com.jwsoft.manager.core.integration.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.bifang.engine.assistant.core.annotation.ApiService;
import com.bifang.engine.assistant.core.annotation.OpApi;
import com.bifang.engine.assistant.core.annotation.SaveOplog;
import com.bifang.engine.assistant.core.enums.AuTypeEnum;
import com.bifang.engine.assistant.core.enums.FuncTypeEnum;
import com.bifang.engine.assistant.core.utils.SessionUtil;
import com.bifang.engine.cache.redis.RedisHelper;
import com.bifang.engine.data.core.util.PagerUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.jwsoft.manager.common.enums.SchoolNatureEnum;
import com.jwsoft.manager.common.vo.eduClass.EduClassCreateVO;
import com.jwsoft.manager.common.vo.eduClassStudent.EduClassStudentVO;
import com.jwsoft.manager.common.vo.eduSchool.EduSchoolVO;
import com.jwsoft.manager.core.dao.model.*;
import com.jwsoft.manager.core.dao.service.*;
import com.jwsoft.manager.core.util.BandingStudentHelper;
import com.jwsoft.manager.core.util.EduDesensitizeUtil;
import com.jwsoft.manager.core.util.EduHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import cn.hutool.core.convert.Convert;

import java.util.ArrayList;
import java.util.List;

import com.bifang.engine.assistant.core.exception.AppException;
import org.springframework.util.ObjectUtils;
import org.springframework.transaction.annotation.Transactional;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.jwsoft.manager.common.vo.eduClass.EduClassVO;
import com.jwsoft.manager.common.vo.eduClass.EduClassKeyVO;
import com.jwsoft.manager.common.vo.eduClass.EduClassQueryVO;
import com.jwsoft.manager.core.integration.EduClassIntegration;

/**
 * 分班信息管理业务实现类
 *
 * @author chenzh
 * @since 2023-08-21
 */
@ApiService(funcCode = "eduClass", title = "分班信息管理")
public class EduClassIntegrationImpl implements EduClassIntegration {

    @Autowired
    public EduClassService eduClassService;
    @Autowired
    private EduHelper eduHelper;
    @Autowired
    private EduSchoolService eduSchoolService;
    @Autowired
    private EduClassStudentService eduClassStudentService;
    @Autowired
    private EduClassStudentKeyService eduClassStudentKeyService;
    @Autowired
    private EduClassSettingService eduClassSettingService;
    @Autowired
    private BandingStudentHelper bandingStudentHelper;
    @Autowired
    private EduClassAdviserService eduClassAdviserService;
    @Autowired
    private RedisHelper redisHelper;
    @Override
    @OpApi(funcCode = "eduClass0001", title = "分班信息管理分页查询", funcType = FuncTypeEnum.query)
    public PageInfo<EduClassVO> getList(EduClassQueryVO vo) {
        // 开启分页
        if (vo.getPageNum() == null || vo.getPageSize() == null) {
            //如果不传入分页参数，默认最大取1000条
            vo.setPageNum(1);
            vo.setPageSize(1000);
        }
        if (vo.getYear() == null) {
            vo.setYear(eduHelper.thisYear());
        }
        if (StringUtils.isBlank(vo.getAreaCode())) {
            vo.setAreaCode(SessionUtil.getAreaCode());
        }
        QueryWrapper<EduClass> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(vo.getAdviserId() != null, EduClass::getAdviserId, vo.getAdviserId())
                .eq(StringUtils.isNotBlank(vo.getAreaCode()), EduClass::getAreaCode, vo.getAreaCode())
                .eq(StringUtils.isNotBlank(vo.getSchoolId()), EduClass::getSchoolId, vo.getSchoolId())
                .eq(StringUtils.isNotBlank(vo.getClassName()), EduClass::getClassName, vo.getClassName())
                .eq(vo.getYear() != null, EduClass::getYear, vo.getYear())
                .eq(vo.getOrderNumber() != null, EduClass::getOrderNumber, vo.getOrderNumber());
        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        List<EduClass> list = eduClassService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            // 判断是否为空，为空则返回空参数
            return PagerUtil.createEmptyPagerInfo(vo.getPageNum(), vo.getPageSize());
        }
        // 不为空则获取分页结果
        PageInfo<EduClass> pageInfo = new PageInfo<>(list);
        // 返回参数需要通过common层的vo实体类，用该方法可以批量转换
        List<EduClassVO> resultList = Convert.toList(EduClassVO.class, pageInfo.getList());
        // 转义数据字典值
        // dictHelper.valueToName(resultList, Arrays.asList(DemoDictEnum.values()));
        return PagerUtil.parsePagerVo(resultList, pageInfo);
    }

    @Override
    @OpApi(funcCode = "eduClass0002", title = "分班信息管理根据主键查询详情", funcType = FuncTypeEnum.query)
    public EduClassVO getById(EduClassKeyVO vo) {
        EduClass entity = eduClassService.getById(vo.getClassId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("查询不到详细信息!");
        }
        EduClassVO result = Convert.convert(EduClassVO.class, entity);
        return result;
    }

    /**
     * 保存前统一校验
     */
    @Override
    @OpApi(funcCode = "eduClass0003", title = "分班信息管理保存前校验", funcType = FuncTypeEnum.other, checkPrivilege = BoolEnum.FALSE)
    public void checkSave(EduClassVO vo) {
        //主键为空为新增校验

        //主键不为空为修改校验
    }

    @Override
    @OpApi(funcCode = "eduClass0004", title = "分班信息管理新增", funcType = FuncTypeEnum.insert)
    @SaveOplog(
            operationType = "eduClass0004",
            operationName = "分班信息管理新增",
            dataType = "classId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduClassVO add(EduClassVO vo) {
        //保存前校验
        checkSave(vo);
        //保存数据
        EduClass entity = Convert.convert(EduClass.class, vo);
        eduClassService.save(entity);
        //将主键设置回vo使操作日志可以取到
        vo.setClassId(entity.getClassId());
        return vo;
    }

    @Override
    @OpApi(funcCode = "eduClass0005", title = "分班信息管理修改", funcType = FuncTypeEnum.update)
    @SaveOplog(
            operationType = "eduClass0005",
            operationName = "分班信息管理修改",
            dataType = "classId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public EduClassVO edit(EduClassVO vo) {
        if (ObjectUtils.isEmpty(vo.getClassId())) {
            throw new AppException("传入需要修改的主键不能为空!");
        }
        EduClass oldEntity = eduClassService.getById(vo.getClassId());
        if (ObjectUtils.isEmpty(oldEntity)) {
            throw new AppException("查询不到需要修改的信息!");
        }
        //保存前校验
        checkSave(vo);
        //保存数据
        EduClass entity = Convert.convert(EduClass.class, vo);
        eduClassService.updateById(entity);
        return vo;
    }

    @Override
    @OpApi(funcCode = "eduClass0006", title = "分班信息管理根据主键删除", funcType = FuncTypeEnum.delete)
    @SaveOplog(
            operationType = "eduClass0006",
            operationName = "分班信息管理删除",
            dataType = "classId",
            auType = AuTypeEnum.OTHER)
    @Transactional
    public void del(EduClassKeyVO vo) {
        if (ObjectUtils.isEmpty(vo.getClassId())) {
            throw new AppException("传入需要删除的数据主键不能为空!");
        }
        EduClass entity = eduClassService.getById(vo.getClassId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new AppException("未找到需要删除的信息!");
        }
        eduClassService.removeById(vo.getClassId());
    }

    @Override
    @OpApi(funcCode = "eduClass0007", title = "分班信息管理-预分班", funcType = FuncTypeEnum.update)
    @Transactional
    public List<EduClassVO> createClass(EduClassCreateVO vo) {
        String redisKey = "edu:createClass";

        redisHelper.set(redisKey, true, 300);
        Integer year = eduHelper.thisYear();
        if (StringUtils.isBlank(vo.getSchoolId())) {
            vo.setSchoolId(SessionUtil.getOrgId());
        }

        EduSchoolVO eduSchoolVO = eduSchoolService.getDetail(vo.getSchoolId());
        if (eduSchoolVO == null) {
            redisHelper.del(redisKey);
            throw new AppException("学校id不能为空");
        }
        if (!SchoolNatureEnum.gb.getType().equalsIgnoreCase(eduSchoolVO.getSchoolNature())) {
            if (StringUtils.isBlank(vo.getConfigTypeName())) {
                redisHelper.del(redisKey);
                throw new AppException("招生类别不能为空");
            }
        } else {
            vo.setConfigTypeName(null);
        }
        QueryWrapper<EduClass> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(EduClass::getYear, year)
                .eq(EduClass::getSchoolId, vo.getSchoolId())
                .eq(StringUtils.isNotBlank(vo.getConfigTypeName()), EduClass::getConfigTypeName, vo.getConfigTypeName());
        if (eduClassService.count(queryWrapper) > 0) {
            eduClassService.remove(queryWrapper);
        }
        //判断是否有分班参数
        QueryWrapper<EduClassSetting> settingQueryWrapper = new QueryWrapper<>();
        settingQueryWrapper.lambda().eq(EduClassSetting::getSchoolId, vo.getSchoolId())
                .eq(EduClassSetting::getYear, year)
                .eq(StringUtils.isNotBlank(vo.getConfigTypeName()), EduClassSetting::getConfigTypeName, vo.getConfigTypeName())
                .eq(EduClassSetting::getEnabled, BoolEnum.TRUE.getType());
        EduClassSetting eduClassSetting = eduClassSettingService.getOne(settingQueryWrapper, false);
        if (eduClassSetting == null) {
            redisHelper.del(redisKey);
            throw new AppException("请先到“分班设置”中配置分班规则");
        }
        if (eduClassSetting.getClassNum() == null || eduClassSetting.getClassNum() <= 0) {
            redisHelper.del(redisKey);
            throw new AppException("请先到“分班设置”中配置班级数");
        }
        if (StringUtils.isBlank(eduClassSetting.getClassParams())) {
            redisHelper.del(redisKey);
            throw new AppException("请先到“分班设置”中配置分班规则");
        }
        List<EduClassVO> classList = new ArrayList<>();
        //进行预分班
        for (int i = 1; i <= eduClassSetting.getClassNum(); i++) {
            EduClassVO eduClass = new EduClassVO();
            eduClass.setSchoolId(vo.getSchoolId());
            eduClass.setSchoolName(eduSchoolVO.getSchoolName());
            eduClass.setAreaCode(eduSchoolVO.getAreaCode());
            eduClass.setYear(year);
            eduClass.setConfigTypeName(vo.getConfigTypeName());
            eduClass.setOrderNumber(i);
            classList.add(eduClass);
        }
        List<EduClass> eduClasseList = Convert.toList(EduClass.class, classList);
        try {
            eduClassService.saveBatch(eduClasseList);
            bandingStudentHelper.banding(eduClassSetting, eduClasseList, eduSchoolVO);
        } catch (AppException e) {
            throw e;
        } catch (Exception e) {
            throw new AppException("系统异常", e);
        } finally {
            redisHelper.del(redisKey);
        }

        return Convert.toList(EduClassVO.class, eduClasseList);
    }

    @Override
    @OpApi(funcCode = "eduClass0008", title = "分班信息管理-查询是否分班", funcType = FuncTypeEnum.query, checkPrivilege = BoolEnum.FALSE)
    public Boolean queryClassFlag(EduClassCreateVO vo) {
        Integer year = eduHelper.thisYear();
        if (StringUtils.isBlank(vo.getSchoolId())) {
            vo.setSchoolId(SessionUtil.getOrgId());
        }
        EduSchoolVO eduSchoolVO = eduSchoolService.getDetail(vo.getSchoolId());
        if (eduSchoolVO == null) {
            throw new AppException("学校id不能为空");
        }
        QueryWrapper<EduClass> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(EduClass::getYear, year)
                .eq(EduClass::getSchoolId, vo.getSchoolId());
        if (eduClassService.count(queryWrapper) > 0) {
            return true;
        }
        return false;
    }

    @Override
    @OpApi(funcCode = "eduClass0009", title = "分班信息管理-根据学校和年度查询分班信息", funcType = FuncTypeEnum.query, checkPrivilege = BoolEnum.FALSE)
    public List<EduClassVO> queryByYearAndSchool(EduClassQueryVO vo) {
        if (vo.getYear() == null) {
            vo.setYear(eduHelper.thisYear());
        }
        if (StringUtils.isBlank(vo.getSchoolId())) {
            vo.setSchoolId(SessionUtil.getOrgId());
        }
        EduSchoolVO eduSchoolVO = eduSchoolService.getDetail(vo.getSchoolId());
        if (eduSchoolVO == null) {
            throw new AppException("学校id不能为空");
        }
        if (!SchoolNatureEnum.gb.getType().equalsIgnoreCase(eduSchoolVO.getSchoolNature())) {
            if (StringUtils.isBlank(vo.getConfigTypeName())) {
                throw new AppException("招生类别不能为空");
            }
        } else {
            vo.setConfigTypeName(null);
        }
        QueryWrapper<EduClass> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(EduClass::getYear, vo.getYear())
                .eq(EduClass::getSchoolId, vo.getSchoolId())
                .eq(StringUtils.isNotBlank(vo.getConfigTypeName()), EduClass::getConfigTypeName, vo.getConfigTypeName());
        List<EduClass> list = eduClassService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<EduClassVO> voList = Convert.toList(EduClassVO.class, list);
        return voList;
    }

    @Override
    @OpApi(funcCode = "eduClass0010", title = "分班信息管理-设置班主任和名称", funcType = FuncTypeEnum.update)
    @Transactional
    public void setAdviser(EduClassVO vo) {
        if (vo.getClassId() == null) {
            throw new AppException("班级id不能为空");
        }
        if (vo.getAdviserId() == null) {
            throw new AppException("班主任不能为空");
        }
        if (StringUtils.isBlank(vo.getClassName())) {
            throw new AppException("班级名称不能为空");
        }
        EduClass eduClass = eduClassService.getById(vo.getClassId());
        if (eduClass == null) {
            throw new AppException("班级信息不存在");
        }
        if (eduClass.getYear() - eduHelper.thisYear() != 0) {
            throw new AppException("只能设置当前年度");
        }

        EduClassAdviser eduClassAdviser = eduClassAdviserService.getById(vo.getAdviserId());
        if (eduClassAdviser == null) {
            throw new AppException("班主任信息不存在");
        }
        eduClass.setClassName(vo.getClassName());
        eduClass.setAdviserId(vo.getAdviserId());
        eduClass.setAdviserName(eduClassAdviser.getFullName());
        //获取重点学生
        QueryWrapper<EduClassStudentKey> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(EduClassStudentKey::getYear, eduClass.getYear())
                .eq(EduClassStudentKey::getSchoolId, eduClass.getSchoolId())
                .eq(EduClassStudentKey::getAdviserId, vo.getAdviserId());
        List<EduClassStudentKey> studentKeyList = eduClassStudentKeyService.list(queryWrapper);
        if (!CollectionUtils.isEmpty(studentKeyList)) {
            for (EduClassStudentKey classStudentKey : studentKeyList) {
                EduClassStudent eduClassStudent = eduClassStudentService.getById(classStudentKey.getStudentId());
                if (eduClassStudent != null && eduClassStudent.getClassId() != null && eduClass.getClassId() - eduClassStudent.getClassId() != 0) {
                    QueryWrapper<EduClassStudent> studentQueryWrapper = new QueryWrapper<>();
                    studentQueryWrapper.lambda().ne(EduClassStudent::getStudentId, eduClassStudent.getStudentId())
                            .eq(EduClassStudent::getYear, eduClassStudent.getYear())
                            .eq(EduClassStudent::getSchoolId, eduClassStudent.getSchoolId())
                            .eq(EduClassStudent::getSex, eduClassStudent.getSex())
                            .eq(EduClassStudent::getClassId, vo.getClassId())
                            .eq(EduClassStudent::getSerialNumber, eduClassStudent.getSerialNumber());
                    List<EduClassStudent> studentList = eduClassStudentService.list(studentQueryWrapper);
                    if (!CollectionUtils.isEmpty(studentList)) {
                        EduClassStudent jhStudent = studentList.get(0);
                        jhStudent.setClassId(eduClassStudent.getClassId());
                        jhStudent.setAdviserId(eduClassStudent.getAdviserId());
                        eduClassStudent.setClassId(vo.getClassId());
                        eduClassStudent.setAdviserId(vo.getAdviserId());
                        eduClassStudentService.updateById(jhStudent);
                        eduClassStudentService.updateById(eduClassStudent);
                    } else {
                        Integer serialNumber = eduClassStudent.getSerialNumber();
                        if (eduClassStudent.getSerialNumber() == 1) {
                            serialNumber = serialNumber + 1;
                        } else {
                            serialNumber = serialNumber - 1;
                        }
                        QueryWrapper<EduClassStudent> studentQueryWrapper1 = new QueryWrapper<>();
                        studentQueryWrapper1.lambda().ne(EduClassStudent::getStudentId, eduClassStudent.getStudentId())
                                .eq(EduClassStudent::getYear, eduClassStudent.getYear())
                                .eq(EduClassStudent::getSchoolId, eduClassStudent.getSchoolId())
                                .eq(EduClassStudent::getSex, eduClassStudent.getSex())
                                .eq(EduClassStudent::getClassId, vo.getClassId())
                                .eq(EduClassStudent::getSerialNumber, serialNumber);
                        List<EduClassStudent> studentList1 = eduClassStudentService.list(studentQueryWrapper1);
                        if (!CollectionUtils.isEmpty(studentList1)) {
                            EduClassStudent jhStudent = studentList1.get(0);
                            jhStudent.setClassId(eduClassStudent.getClassId());
                            jhStudent.setAdviserId(eduClassStudent.getAdviserId());
                            eduClassStudent.setClassId(vo.getClassId());
                            eduClassStudent.setAdviserId(vo.getAdviserId());
                            eduClassStudentService.updateById(jhStudent);
                            eduClassStudentService.updateById(eduClassStudent);
                        }
                    }
                }
            }
        }
        eduClassService.updateById(eduClass);
        //更新学生名单表
        UpdateWrapper<EduClassStudent> eduClassStudentUpdateWrapper = new UpdateWrapper<>();
        eduClassStudentUpdateWrapper.lambda().eq(EduClassStudent::getSchoolId, eduClass.getSchoolId())
                .eq(EduClassStudent::getYear, eduClass.getYear())
                .eq(EduClassStudent::getClassId, eduClass.getClassId())
                .set(EduClassStudent::getAdviserId, vo.getAdviserId());
        eduClassStudentService.update(eduClassStudentUpdateWrapper);
    }

    @Override
    @OpApi(funcCode = "eduClass0011", title = "分班信息管理-根据分班id查询学生名单", funcType = FuncTypeEnum.query)
    public List<EduClassStudentVO> getStudentByClassId(EduClassKeyVO vo) {
        if (vo.getClassId() == null) {
            throw new AppException("分班id不能为空");
        }
        if (vo.getDesensitizeFlag() == null) {
            vo.setDesensitizeFlag(true);
        }
        EduClass eduClass = eduClassService.getById(vo.getClassId());
        if (eduClass == null) {
            throw new AppException("班级信息不存在");
        }
        QueryWrapper<EduClassStudent> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(EduClassStudent::getSchoolId, eduClass.getSchoolId())
                .eq(EduClassStudent::getYear, eduClass.getYear())
                .eq(EduClassStudent::getClassId, eduClass.getClassId())
                .orderByAsc(EduClassStudent::getFullName);
        List<EduClassStudent> list = eduClassStudentService.list(queryWrapper);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<EduClassStudentVO> voList = Convert.toList(EduClassStudentVO.class, list);
        for (EduClassStudentVO studentVO : voList) {
            studentVO.setAdviserName(eduClass.getAdviserName());
            studentVO.setClassName(eduClass.getClassName());
            studentVO.setOrderNumber(eduClass.getOrderNumber());
            if (vo.getDesensitizeFlag()) {
                EduDesensitizeUtil.desensitizeStudentClass(studentVO);
            }
        }
        return voList;
    }
}
